﻿/*
 * Created by SharpDevelop.
 * User: issuser
 * Date: 2010-12-9
 * Time: 13:31
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Linq;
using System.Data;
using System.Data.Common;
using System.Data.SqlTypes;
using System.Collections.Generic;
using NLite.Data;
using NLite.Log;
using NLite.ComponentModel;
using NLite.Collections;
using NLite.Data.Schema;


namespace NLite.Data.Driver
{
   

	/// <summary>
	/// Description of IDriver.
	/// </summary>
	public interface IDriver
	{
		bool UseNamedPrefixInSql { get; }
		bool UseNamedPrefixInParameter { get; }
		string NamedPrefix { get; }
        bool SupportsMultipleOpenReaders { get; }
        bool SupportsPreparingCommands{ get;}
        bool SupportsMultipleQueries{ get;}
        bool SupportsCollectionOperation { get; }
        bool SupportsSubQuery { get; }
        bool IsPrepareSqlEnabled { get; set; }

        string ConnectionString { get; set; }
        int? CommandTimeout { get; set; }

        ISchemaProvider SchemaProvider { get; set; }

        DbConnection CreateConnection();

        void PrepareCommand(IDbCommand cmd, CommandType type, string sqlString, params IDataParameter[] ps);
        IDbDataParameter GenerateParameter(IDbCommand command, IDataParameter p);
    }

    public interface ITransaction : IDbTransaction
    {
        bool IsActive { get; }
        bool WasRolledBack { get; }
        bool WasCommitted { get; }
        void Enlist(IDbCommand command);
    }

    public static class DriverExtensions
    {
        public static DataTable GetDateTable(this IDriver Driver, IQuery query)
        {
            using (var reader = ExecuteReader(Driver,query))
            {
                var tb = reader.ToDataTable();
                tb.TableName = query.Node.Name;
                return tb;
            }
        }

        public static IDataReader ExecuteReader(this IDriver Driver, IQuery query)
        {
            var conn = Driver.CreateConnection();
            using (var cmd = conn.CreateCommand())
            {
                var rs = query.Result;

                Driver.PrepareCommand(cmd, CommandType.Text, rs.Text, rs.Parameters.ToArray());
                conn.Open();
                var reader = cmd.ExecuteReader();

                return reader;
            }
        }

        public static DataTable ExecuteDataTable(this IDriver Driver, IQuery query)
        {
            using (var conn = Driver.CreateConnection())
            using (var cmd = conn.CreateCommand())
            {
                var rs = query.Result;

                Driver.PrepareCommand(cmd, CommandType.Text, rs.Text, rs.Parameters.ToArray());
                conn.Open();
                using (var reader = cmd.ExecuteReader())
                    return reader.ToDataTable();
            }
        }

        public static T ExecuteScalar<T>(this IDriver Driver, IQuery query)
        {
            using (var conn = Driver.CreateConnection())
            using (var cmd = conn.CreateCommand())
            {
                var rs = query.Result;

                Driver.PrepareCommand(cmd, CommandType.Text, rs.Text, rs.Parameters.ToArray());
                conn.Open();
                return cmd.ExecuteScalar<T>();
            }
        }

        public static IEnumerable<T> ExecuteScalarList<T>(this IDriver Driver, IQuery query)
        {
            using (var conn = Driver.CreateConnection())
            using (var cmd = conn.CreateCommand())
            {
                var rs = query.Result;

                Driver.PrepareCommand(cmd, CommandType.Text, rs.Text, rs.Parameters.ToArray());
                conn.Open();
                return cmd.ExecuteScalarList<T>();
            }
        }

        public static int ExecuteNonQuery(this IDriver Driver, IUpdateQuery query)
        {
            using (var conn = Driver.CreateConnection())
            using (var cmd = conn.CreateCommand())
            {
                var rs = query.Result;

                Driver.PrepareCommand(cmd, CommandType.Text, rs.Text, rs.Parameters.ToArray());
                conn.Open();
                return cmd.ExecuteNonQuery();
            }
        }
    }
}
